package com.pro.common.service.sitecontent.service;

import com.pro.common.api.enums.EnumSysRole;
import com.pro.common.api.model.ILoginInfo;
import com.pro.common.api.service.ITranslateDateService;
import com.pro.common.service.util.I18nUtils;
import com.pro.common.service.sitecontent.dao.AuthRouteDao;
import com.pro.common.service.sitecontent.model.db.AuthRoute;
import com.pro.framework.api.database.IContext;
import com.pro.framework.api.database.TimeQuery;
import com.pro.framework.api.database.page.IPageInput;
import com.pro.framework.api.database.page.PageInput;
import com.pro.framework.api.enums.IEnumToDbEnum;
import com.pro.framework.api.util.AssertUtil;
import com.pro.framework.core.EnumConstant;
import com.pro.framework.core.EnumUtil;
import com.pro.framework.mtq.service.multiwrapper.dto.MultiPageResult;
import com.pro.framework.mtq.service.multiwrapper.entity.IMultiPageResult;
import com.pro.framework.mybatisplus.BaseService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * 国家 服务实现类
 */
@Service
@Slf4j
public class AuthRouteService extends BaseService<AuthRouteDao, AuthRoute> implements ITranslateDateService {
//    private final CommonProperties commonProperties;
//
//    public AuthRouteService(CommonProperties commonProperties) {
//        super();
//        this.commonProperties = commonProperties;
//    }

    public List<AuthRoute> getList(EnumSysRole role, Set<String> codes) {
        return this.lambdaQuery()
                .eq(AuthRoute::getSysRole, role)
                .eq(AuthRoute::getEnabled, true)
                .in(null != codes, AuthRoute::getCode, codes)
                .list();
    }

    @Override
    public List<AuthRoute> selectList(IContext context, String entityClassNames, Map<String, Object> paramMap, TimeQuery timeQuery, List<String> selects, List<String> selectMores, List<String> selectLess, PageInput pageInput) {
        AssertUtil.isTrue(context instanceof ILoginInfo, "暂无权限");
        //noinspection DataFlowIssue
        ILoginInfo loginInfo = (ILoginInfo) context;
        return this.filterAndTranslate(loginInfo, paramMap,
                (paramMapNew) -> super.selectList(context, entityClassNames, paramMapNew, timeQuery, selects, selectMores,
                        selectLess, pageInput));
    }

    protected List<AuthRoute> filterAndTranslate(ILoginInfo loginInfo, Map<String, Object> paramMap, Function<Map<String, Object>, List<AuthRoute>> queryListFunction) {
        paramMap = new HashMap<>(paramMap);
//        log.info("LoginInfoContext.get {}", LoginInfoContext.get());
        EnumSysRole sysRole = loginInfo.getSysRole();
        paramMap.put("groupCode", loginInfo.getAuthRouteGroupCode());
        switch (sysRole) {
            case ADMIN:
                break;
            case AGENT:
//                paramMap.put("enabled", null);
                paramMap.remove("enabled");
                break;
            default:
                paramMap.put("sysRole", sysRole);
                break;
        }
        List<AuthRoute> authRoutes = queryListFunction.apply(paramMap);
//        authRoutes = authRoutes.stream().filter(authRoute -> authRoute.getGroupCode().equals(loginInfo.getAuthRouteGroupCode())).collect(Collectors.toList());
        switch (sysRole) {
            case USER:
            case ANONYMOUS:
                return authRoutes;
            case AGENT:
                Map<String, List<AuthRoute>> listMap = authRoutes.stream()
                        .collect(Collectors.groupingBy(AuthRoute::getCode));
                return listMap.values().stream().map(routes -> {
                    AuthRoute authRouteAgent = routes.stream()
                            .filter(r -> EnumSysRole.AGENT.equals(r.getSysRole()))
                            .findFirst()
                            .orElse(null);
                    AuthRoute authRouteAdmin = routes.stream()
                            .filter(r -> EnumSysRole.ADMIN.equals(r.getSysRole()))
                            .findFirst()
                            .orElse(null);
                    if (authRouteAgent == null) {
                        return authRouteAdmin;
                    } else if (authRouteAgent.getEnabled()) {
                        return authRouteAgent;
                    }
                    return null;
                }).filter(Objects::nonNull).collect(Collectors.toList());
            case ADMIN:
        }
        authRoutes.forEach(authRoute -> authRoute.setRouteName(I18nUtils.get(authRoute.getRouteName())));
        return authRoutes;
    }


    @Override
    public IMultiPageResult<AuthRoute> selectPage(IContext context, String entityClassNames, IPageInput pageInput, Map<String, Object> paramMap, TimeQuery timeQuery) {
        MultiPageResult<AuthRoute> page = new MultiPageResult<>();
        page.setRecords(this.filterAndTranslate((ILoginInfo) context, paramMap,
                (paramMapNew) -> super.selectPage(context, entityClassNames, pageInput, paramMapNew, timeQuery).getRecords()));
        return page;
    }

    @Override
    public boolean updateById(IContext context, AuthRoute entity) {
        entity.setRouteName(null);// 翻译统一,暂时不可编辑
        return super.updateById(context, entity);
    }

    @Override
    public List<String> getTranslateKeys(boolean isCommon) {
        Class<IEnumToDbEnum> intf = IEnumToDbEnum.class;
        Set<Class> enumClasses = EnumConstant.simpleNameClassMapNoReplace.values()
                .stream()
                .filter(intf::isAssignableFrom)
                .filter(c -> c.getPackage().getName().startsWith("com.pro.common.module.service."))
                .collect(Collectors.toSet());
        Set<String> baseCodes = enumClasses.stream()
                .flatMap(c -> ((List<Enum>) EnumUtil.enumList(c)).stream())
                .map(Enum::name)
                .collect(Collectors.toSet());
        return this.list().stream().filter(e -> isCommon == baseCodes.contains(e.getCode()))
                .flatMap(authRoute -> Stream.of(authRoute.getRouteName(), authRoute.getRemark())).distinct().collect(Collectors.toList());
    }
}
